%{
#include "info.h"
#include "treenode.h" 
#define YYSTYPE treenode *
#include "syntax.tab.h" 


int yycolumn = 1;
extern int err;

#define lexAction(lexTypeName,val)  do{ \
    treenode *node = newTNode(#lexTypeName, val); \
    yylval = node; \
    return lexTypeName; \
    } while (0)                                       

#define YY_USER_ACTION \
    yylloc.first_line = yylloc.last_line = yylineno; \
    yylloc.first_column = yycolumn; \
    yylloc.last_column = yycolumn + yyleng - 1; \
    yycolumn += yyleng;
%}
%option yylineno

ws [ \t\r]+
TYPE int|float
STRUCT struct
RETURN return
IF if
ELSE else
WHILE while
num [0-9]
pos [1-9]
oct  0[0-7]+
hex  0[xX][0-9A-Fa-f]+
INT 0|{pos}{num}{0,9}
exponent    [eE][+-]?{num}+
normfloat   {num}+\.{num}+
scifloat    ({num}+\.{num}*|{num}*\.{num}+){exponent}
FLOAT       {normfloat}|{scifloat}
inv_ID      {num}[_0-9A-Za-z]*
ID [_A-Za-z][_0-9A-Za-z]{0,30}
SEMI ;
COMMA ,
ASSIGNOP =
RELOP >|<|>=|<=|==|!=
PLUS \+
MINUS -
STAR \*
DIV \/
AND &&
OR "||"
DOT "."
NOT "!"
LP \(
RP \)
LB \[
RB \]
LC \{
RC \}
%%

\n { yycolumn = 1; }
{ws} { /* empty */ }
{TYPE} { lexAction(TYPE,yytext); }
{STRUCT} { lexAction(STRUCT,yytext); }
{RETURN} { lexAction(RETURN,yytext); }
{IF} { lexAction(IF,yytext); }
{ELSE} { lexAction(ELSE,yytext); }
{WHILE} { lexAction(WHILE,yytext); }
{oct} { char str[50]; 
        sprintf(str,"%d",strtol(yytext,NULL,8));
        //myitoa(strtol(yytext,NULL,8), str); 
        lexAction(INT, str); 
    }
{hex} { char str[50]; 
        sprintf(str,"%d",strtol(yytext,NULL,16));
        //myitoa(strtol(yytext,NULL,16), str); 
        lexAction(INT, str); 
    }
{INT} { lexAction(INT,yytext); }
{FLOAT} { char str[50];
        sprintf(str,"%f",strtof(yytext,NULL));
        lexAction(FLOAT,str); }
{ID} { lexAction(ID,yytext); }
{inv_ID} { printLexMsg(INV_ID); }
{SEMI} { lexAction(SEMI,yytext); }
{COMMA} { lexAction(COMMA,yytext); }
{ASSIGNOP} { lexAction(ASSIGNOP,yytext); }
{RELOP} { lexAction(RELOP,yytext); }
{PLUS} { lexAction(PLUS,yytext); }
{MINUS} { lexAction(MINUS,yytext); }
{STAR} { lexAction(STAR,yytext); }
{DIV} { lexAction(DIV,yytext); }
{AND} { lexAction(AND,yytext); }
{OR} { lexAction(OR,yytext); }
{DOT} { lexAction(DOT,yytext); }
{NOT} { lexAction(NOT,yytext); }
{LP} { lexAction(LP,yytext); }
{RP} { lexAction(RP,yytext); }
{LB} { lexAction(LB,yytext); }
{RB} { lexAction(RB,yytext); }
{LC} { lexAction(LC,yytext); }
{RC} { lexAction(RC,yytext); }
. {
    //printf("Error type A at Line %d: Mysterious characters \'%s\'\n",yylineno, yytext);
    printLexMsg(INV_CHAR);
}
%%
void printLexMsg(int num)
{
    err = 1;
    fprintf(stderr,"Error type A at Line %d: %s \"%s\".\n",yylineno, lexErrMsg[num], yytext);
}
void myitoa(int num, char* str)
{
    int n = 0;
    if(num == 0)
        {str[0] = 0;n++;return;}
    while(num != 0)
    {
        str[n++] = '0'+num%10;
        num/=10;
    }
    //printf("%d\n",n);
    for(int i = 0;i<n/2;i++)
    {
        char ch = str[i];
        str[i] = str[n-1-i];
        str[n-1-i] = ch;
    }
    str[n] = 0;
}
